package com.zxr.diana.core;

import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author xuerui.zhang
 * @since 2019-06-18 10:15
 */
public class ClassScanner {

    public static List<Class<?>> loadClasses(String packageName)
            throws IOException, ClassNotFoundException {
        if (packageName == null) {
            return Collections.emptyList();
        }
        String path = packageName.replace(".", "/");
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> resources = classLoader.getResources(path);
        List<Class<?>> classList = new ArrayList<>();
        while (resources.hasMoreElements()) {
            URL url = resources.nextElement();
            if (url.getProtocol().contains("jar")) {
                JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                String jarFilePath = jarURLConnection.getJarFile().getName();
                classList.addAll(loadCLassFromJarPath(jarFilePath, path));
            }
        }
        return classList;
    }

    private static List<Class<?>> loadCLassFromJarPath(String jarFilePath, String path)
            throws IOException, ClassNotFoundException {

        List<Class<?>> classList = new ArrayList<>();
        JarFile jarFile = new JarFile(jarFilePath);
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            String entryName = jarEntry.getName();
            if (entryName.startsWith(path) && entryName.endsWith(".class")) {
                String className = entryName.replaceAll("/", ".").substring(0, entryName.length() - 6);
                classList.add(Class.forName(className));
            }
        }
        return classList;
    }
}
